/**
* @author maze | guavestudios.com
* @license MIT License see LICENSE.TXT
* @version 0.1
*/
package com.guavestudios.fcon.plugins {
	import com.guavestudios.fcon.util.KeyMatcher;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.ui.Keyboard;
	import flash.display.*;
	import flash.utils.*;
	import com.guavestudios.fcon.api.IControlableConsole;
	import com.guavestudios.fcon.ConsoleImpl;
	import com.guavestudios.fcon.events.ConsoleKeyboardEvent;
	import com.guavestudios.fcon.core.*;

	public class AutoCompletion implements IConsolePlugin {
		
		//{ STATIC
		public static const CONFIG_COMP_KEY:String = "AutoCompletion.Key";
		public static const DEFAULT_KEY:String = "Key.TAB";
		//}
		
		//{ MEMBERS
		private var console:IControlableConsole;
		private var pathParser:IPathParser;
		private var completionKey:KeyMatcher;
		private var _constants:IConstantsProvider;
		//}
		
		//{ GETTER-SETTER
		
		//}
		public function AutoCompletion() {
			
			
			init();	
		}
		private function init():void {
			
		}
		//{ PUBLIC FUNCTIONS
		/**
		* Called when the plugin is finally loaded
		* @param	c
		*/
		public function initPlugin(c:IControlableConsole):void
		{
			console=c;
			pathParser=c.getPathParser(); //use pathparser from stage
			c.addEventListener(ConsoleKeyboardEvent.INPUT_KEYUP, on_keyup);
			
			var s:String = DEFAULT_KEY;
			if (c.hasConfig(CONFIG_COMP_KEY))
			{
				s = c.getConfig(CONFIG_COMP_KEY).toString();
			}
			completionKey = KeyMatcher.createMatcher(s);
			
			if (c.hasPlugin("ConstantsPlugin"))
			{
				_constants = IConstantsProvider(c.getPlugin("ConstantsPlugin"));
			}
		}
		/**
		* Request the unload for the plugin
		*/
		public function unloadPlugin():void
		{
			console.removeEventListener(ConsoleKeyboardEvent.INPUT_KEYUP, on_keyup);
			_constants = null;
			console = null;

		}
		/**
		* Current state of the plugin see @see com.guavestudios.fcon.plugins.PluginState
		*/
		public function get State():int
		{
			return 0;
		}
		/**
		* Plugin name
		*/
		public function get Name():String
		{
			return "AutoCompletion";
		}
		/**
		* Plugin version
		*/
		public function get Version():String
		{
			return "0.0";
		}
		
		public function get constants():IConstantsProvider { return _constants; }
		
		public function set constants(value:IConstantsProvider):void {
			_constants = value;
		}
		//}
		
		//{ OVERRIDEN METHODS
		
		//}
		
		//{ PRIVATE FUNCTIONS
		private function on_keyup(e:ConsoleKeyboardEvent):void
		{
			if (completionKey.matchEvent(e.getInnerEvent()))
			{
				e.getInnerEvent().stopImmediatePropagation();
				var ip:TextField=ConsoleImpl(console).getInput();
				
				if (ip.text.length>0)
					if (ip.text.charCodeAt(ip.text.length - 1) == completionKey.char)
						ip.text = ip.text.substr(0, ip.text.length - 1);
				
				tabpressed();
				
				ConsoleImpl(console).setInputFocus();
				
				ip.setSelection(ip.text.length,ip.text.length);
			}
			
		}
		
		private function tabpressed():void
		{
			var input:TextField=ConsoleImpl(console).getInput();
			
			var c:int=input.caretIndex; //full text
			var txt:String=input.text; //text
			
			var ll:int = txt.lastIndexOf(" ", c); //last space
			var lastpoint:int = txt.lastIndexOf(".", c); //last point
			
			var parsetxt:String;
			
			var foundcmd:Array=new Array();
			
			if (ll<0)
			{
				//its a command
				var cmds:Dictionary=console.getCommands();
				
				for (var i:String in cmds)
					if (i.substr(0,txt.length)==txt)
						foundcmd.push(i);
						
				if (foundcmd.length==1)
				{
					input.text=foundcmd[0]+" ";
					input.setSelection(input.text.length,input.text.length);
				}
				else if (foundcmd.length==0)
				{
					console.outputText("cmds: none found");
				}
				else
				{
					console.outputText("cmds: "+foundcmd.join(" "));
				}
			}
			else if (c-ll>0)
			{
				var ps:String;
				if (lastpoint > ll) {
					parsetxt = txt.substring(ll + 1, lastpoint);
					ps = txt.substring(0, lastpoint+1);
				}
				else {
					parsetxt = txt.substring(ll + 1, c);
					ps = txt.substring(0,ll+1);
				}
				
				try {
					
					var a:Array 
					if (lastpoint > 0)
						a = pathParser.parse(parsetxt);
					else
					{
						var re:PathElement = new PathElement();
						re.setElement(pathParser.getNavigateObject());
						a = [re];
					}
					
					
					
					
					var le:PathElement = a[a.length - 1]; //getting the last element
					var ss:String = input.text.substring(lastpoint + 1, c);
					if (lastpoint < 0) ss = parsetxt;
					
					if (le!=null)
					{
						if (ss.charAt(0)=="@")
						{
							if (le.getElement() is DisplayObjectContainer)
							{
								var castle:DisplayObjectContainer=le.getElement() as DisplayObjectContainer;
								
								if (castle.numChildren==0) 
								{
									console.outputText("no childs");
									return;
								}
								else if (castle.numChildren==1)
								{
									input.text==ps+"@0";
									input.setSelection(txt.length-1,txt.length-1);
									return;
								}
								else
								{
									var oos:String="";
									for (var x:int=0; x<castle.numChildren; x++)
										oos+=" @"+x;
									console.outputText("#"+castle.name+":"+oos);
									
								}
							}
							
						}
						else if (ss.charAt(0)=="#")
						{
							if (le.getElement() is DisplayObjectContainer)
							{
								var castle1:DisplayObjectContainer=le.getElement() as DisplayObjectContainer;
								
								if (castle1.numChildren==0) 
								{
									console.outputText("no childs");
									return;
								}
								else if (castle1.numChildren==1)
								{
									input.text=ps+"#"+castle1.getChildAt(0).name;
									input.setSelection(txt.length-1,txt.length-1);
									return;
								}
								else
								{
									var cname:String;
									for (var j:int=0; j<castle1.numChildren; j++)
									{
										cname=castle1.getChildAt(j).name;
										if (cname.substr(0,ss.length-1)==ss.substring(1))
										{
											foundcmd.push(cname);
										}
										
									}
									if (foundcmd.length==1)
									{
										input.text=ps+"#"+foundcmd[0];
										input.setSelection(txt.length-1,txt.length-1);
									}
									else 
										console.outputText("#"+castle1.name+": #"+foundcmd.join(" #"));
								}
							}
						}
						else if (_constants!=null && ss.charAt(0)=="$")
						{
							var pcs:Array = _constants.getConstantIds();
							var matchConsts:Array=[];
							
							for each (var cid:String in pcs)
							{
								if (cid.substr(0, ss.length - 1) == ss.substr(1) || ss.length==1)
									matchConsts.push(cid);
							}
							if (matchConsts.length == 1)
							{
								input.text=ps+"$"+matchConsts[0];
								input.setSelection(txt.length-1,txt.length-1);
							}
							else if (matchConsts.length > 1)
							{
								var mcs:String = "";
								for each (var maconst:String in matchConsts)
									mcs += " $" + maconst;
								console.outputText("found: " + mcs);
							}
							else
							{
								console.outputText(ss+": no matching constant found");
							}
							
						}
						else
						{
							var xml:XML = describeType(le.getElement());
							//trace(xml);
							var l:XMLList = xml.children();
							var s:String;

							for each (var o:XML in l)
							{
								s=o.@name;
								if (s.substr(0,ss.length)==ss && o.children().length()==0)
								{
									foundcmd.push(s);
								}	
							}
							if (foundcmd.length==1) 
							{
								input.text=ps+foundcmd[0];
								input.setSelection(txt.length-1,txt.length-1);
							}
							else if (foundcmd.length>1) console.outputText(le.getElementId()+": "+foundcmd.join(" "));
						}
					}
				}
				catch (er:Error)
				{
					console.outputText("path: not valid");
				}
				
				
			}
			
		}
		//}

	}
	
}
